Abraxus's Blog

Battelle Anti-Debugging Write Up

Details:

Jeopardy style CTF

Category: Reverse Engineering

Points: 200

Comments:

Heard you liked debugging... Try this ;)

The flag will be revealed when you pass in the correct input

Write up:

Opening the main function in a decompiler I see:

int __cdecl main(int argc, const char **argv, const char **envp)
{

  v3 = alloca(16);
  __main();
  patchAttach();
  if ( findAndDetach() != 5 || debugged() == 1 || (unsigned __int8)checkForOlly() )
  {
    printf("Debugger Detected\n");
  }
  else
  {
    lpAddress[0] = (LPVOID)getRetAddress();
    VirtualProtect(lpAddress[0], 0x10u, 4u, &flOldProtect);
    *(_DWORD *)(getRetAddress() + 391) = 36859568;
  }
  v4 = GlobalAlloc(0x42u, 0xA000u);
  v16 = GlobalLock(v4);
  VirtualProtect(v16, 0xA000u, 4u, (PDWORD)lpAddress);
  v5 = (void *)findPointer(v16);
  qmemcpy(v5, (const void *)(getRetAddress() + 25), 0xA000u);
  v6 = (void (__stdcall *)(int))findPointer(v16);
  v6(v11);
  printf("Serial: ");
  fgets(Buffer, 100, (FILE *)__iob[0]._ptr);
  if ( debugged() != 1 && getRetAddress() < (unsigned int)v16 + 0x4000 )
  {
    printf("Checking serial...\n");
    *(_DWORD *)(findPointer(checkPass) + 83) = 42468652;
    v14 = (unsigned __int8 (__cdecl *)(char *))findPointer(checkPass);
    if ( v14(Buffer) )
    {
      qmemcpy(Str, &unk_40303C, 0x2Cu);
      for ( i = 0; ; ++i )
      {
        v7 = strlen(Str);
        if ( i >= v7 )
          break;
        v8 = &Str[i];
        v9 = Str[i] ^ 0x80;
        *v8 = v9;
        *v8 = v9;
      }
      printf("%s\n", Str);
    }
    else
    {
      printf("Serial Incorrect.\n");
    }
    printf("press a key to quit.");
    getchar();
  }
  return 0;
}

I wanted to debug this, especially since it's obvious they put lots of antidebugger checks in so I rebased the program and then started nopping out instructions that checked for debugging:

0000132A E8 16 03 00 00                                call    _findAndDetach

00001334 E8 1E 02 00 00                                call    _debugged

0000133E E8 C7 02 00 00                                call    _checkForOlly

00001407 FF D0                                         call    eax

0000143C E8 16 01 00 00                                call    _debugged

After nopping out these instructions I was able to debug, and by changing the z flag as I went I was able to go into the following:

 if ( v12(Buffer) )

This resolved to the following function:

BOOL __cdecl checkPass(char *Str2)
{

  *(_DWORD *)Str = dword_403113;
  v5 = dword_403117;
  v6 = word_40311B;
  v7 = byte_40311D;
  for ( i = 0; i < strlen(Str); ++i )
  {
    Str[i] -= 5;
    Str[i] ^= 0x6Eu;
  }
  v1 = strlen(Str);
  return strncmp(Str, Str2, v1) == 0;
}

Str ended up resolving to: youFoundMe.

When I used that in the program I got:

Correct. user = part6 pass = unpackedSerial

The flag ended up being:

unpackedSerial